const path = require("path");
const ESLintWebpackPlugin = require("eslint-webpack-plugin"); //添加eslint语法检测
const HtmlWebpackPlugin = require("html-webpack-plugin"); // 将html自动引入js
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); //将css打包成css文件，html可以使用link标签引用
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin"); //将css进行压缩
const TerserPlugin = require("terser-webpack-plugin");
const ImageMinimizerPlugin = require("image-minimizer-webpack-plugin");

// nodejs核心模块，直接使用
const os = require("os");
// cpu核数
const threads = os.cpus().length;



// 获取处理样式的loader
const getStyleloaders = (pre) => {
    return [MiniCssExtractPlugin.loader, 
        "css-loader",
        // 兼容css
        {
            loader: "postcss-loader",
            options: {
              postcssOptions: {
                plugins: [
                  "postcss-preset-env", // 能解决大多数样式兼容性问题
                ],
              },
            },
          },
          pre
    ].filter(Boolean)
}

module.exports = {
    // 入口
    // 相对路径和绝对路径都行
    entry: "./src/main.js",
    // 输出
    output: {
        // path: 文件输出目录，必须是绝对路径
        // path.resolve()方法返回一个绝对路径
        // __dirname 当前文件的文件夹绝对路径
        path: path.resolve(__dirname, "../dist"),
        // filename: 输出文件名
        filename: "static/js/main.js",
        // 自动清空上次打包内容
        // 原理，在打包前，将整个path目录内容清空，再进行打包。
        clean: true
    },
    // 加载器
    module: {
        rules: [
            {
                oneOf: [
                    {
                        test: /\.css$/i,
                        use: getStyleloaders(),
                    },
                    {
                        test: /\.less$/i,
                        use: getStyleloaders('less-loader'),
                    },
                    {
                        test: /\.s[ac]ss$/i,
                        use: getStyleloaders('sass-loader'),
                    },
                    {
                        test: /\.styl$/,
                        use: getStyleloaders('stylus-loader'), // 将 Stylus 文件编译为 CSS
                    },
                    {
                        test: /\.(png|jpe?g|gif|webp)$/,
                        type: "asset",
                        parser: {
                            dataUrlCondition: {
                            maxSize: 12 * 1024 // 小于12kb的图片会被base64处理
                            }
                        },
                        generator: {
                            // 将图片文件输出到 static/imgs 目录中
                            // 将图片文件命名 [hash:8][ext][query]
                            // [hash:8]: hash值取8位
                            // [ext]: 使用之前的文件扩展名
                            // [query]: 添加之前的query参数
                            filename: "static/imgs/[hash:8][ext][query]",
                          },
                    } ,
                    {
                        test: /\.(ttf|woff|woff2|mp3|mp4|avi)$/,
                        type: "asset/resource",
                        generator: {
                            filename: "static/media/[hash:8][ext][query]",
                          },
                    },
                    {
                        test: /\.js$/,
                        exclude: /node_modules/, // 排除node_modules代码不编译
                        use: [
                            {
                                loader: "thread-loader", // 开启多进程
                                options: {
                                  workers: threads, // 数量
                                },
                            },
                            {
                                loader: "babel-loader",
                                // include: path.resolve(__dirname, "../src"), // 也可以用包含
                                options: {
                                    cacheDirectory: true, // 开启babel编译缓存
                                    cacheCompression: false,// 缓存文件不要压缩
                                    plugins: ["@babel/plugin-transform-runtime"], // 减少代码体积
                                },
                            }
                        ]
                    },
                ]
            }
        ],
    },
    // 插件
    plugins: [
        new ESLintWebpackPlugin({
            // 指定检查文件的根目录
            context: path.resolve(__dirname, "../src"),
            exclude: "node_modules", // 默认值
            cache: true,
            // 缓存目录
            cacheLocation: path.resolve(__dirname,"../node_modules/.cache/.eslintcache"),
            threads,

        }),
        new HtmlWebpackPlugin({
            // 以 public/index.html 为模板创建文件
            // 新的html文件有两个特点：1. 内容和源文件一致 2. 自动引入打包生成的js等资源
            template: path.resolve(__dirname, "../public/index.html")
        }),
         // 提取css成单独文件
        new MiniCssExtractPlugin({
        // 定义输出文件名和目录
        filename: "static/css/main.css"
        }),
        // css压缩
        // new CssMinimizerPlugin(),
    ],
    optimization: {
        minimize: true,
        minimizer: [
          // css压缩也可以写到optimization.minimizer里面，效果一样的
          new CssMinimizerPlugin(),
          // 当生产模式会默认开启TerserPlugin，但是我们需要进行其他配置，就要重新写了
          new TerserPlugin({
            parallel: threads // 开启多进程
          }),
          // 压缩图片
          new ImageMinimizerPlugin({
            minimizer: {
                implementation: ImageMinimizerPlugin.imageminGenerate,
                options:{
                    plugins: [
                        ["gifsicle", {interlaced: true}],
                        ["jpegtran", {progressive: true}],
                        ["optipng", {optimizationLevel: 5}],
                        [
                            "svgo",
                            {
                                plugins: [
                                    "preset-default",
                                    "prefixIds",
                                    {
                                        name: "sortAttrs",
                                        params: {
                                            xmInsOrders: "alphabetical"
                                        }
                                    }
                                ]
                            }
                        ]
                    ]
                }
            }
          })
        ],
      },
    // 开发服务器
//   devServer: {
//     host: "localhost", // 启动服务器域名
//     port: "3000", // 启动服务器端口号
//     open: true, // 是否自动打开浏览器
//   },
    // 模式
    mode: "production", //开发模式
    devtool: "source-map",

}